#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include "clang-c/Index.h"
#include <stdbool.h>
#include <fcntl.h>


char* findingString = "Init";
int numOfArgc = 0;

bool printKindSpelling(CXCursor cursor) {
    enum CXCursorKind curKind = clang_getCursorKind(cursor);
    const char *curkindSpelling = clang_getCString(
                                  clang_getCursorKindSpelling(curKind));
    if(curKind==4)
    printf("**************\n");
    if(curKind==44)
    printf("44444444444\n");
    printf("kind: %s\n", curkindSpelling);
    return true;
}

bool printSpelling(CXCursor cursor) {
    const char *astSpelling = clang_getCString(clang_getCursorSpelling(cursor));
    printf("name: %s    ", astSpelling);
    return true;
}

bool printLocation(CXCursor cursor) {
    CXSourceRange range = clang_getCursorExtent(cursor);
    CXSourceLocation startLocation = clang_getRangeStart(range);
    CXSourceLocation endLocation = clang_getRangeEnd(range);

    CXFile file;
    unsigned int line, column, offset;
    clang_getInstantiationLocation(startLocation, &file, &line, &column, &offset);
  //  printf("Start: Line: %u Column: %u Offset: %u\n", line, column, offset);
    clang_getInstantiationLocation(endLocation, &file, &line, &column, &offset);
 //   printf("End: Line: %u Column: %u Offset: %u\n", line, column, offset);

    return true;
}

enum CXChildVisitResult printVisitor(CXCursor cursor, CXCursor parent,
                                     CXClientData client_data) {
    char *astSpelling = clang_getCString(clang_getCursorSpelling(cursor));
  //int curLevel = client_data;
  // printf("%d\n",*client_data);
 // printf("%d\n",*(reinterpret_cast<unsigned int*>(client_data));
    if (numOfArgc == 3) {
        if (strcmp(astSpelling, findingString) == 0) {
            printSpelling(cursor);
            printKindSpelling(cursor);
         //   printLocation(cursor);
        }
    } else {
     
        printSpelling(cursor);
        printKindSpelling(cursor);
       // printLocation(cursor);
    }
 
    return CXChildVisit_Recurse;
}

int main(int argc, char *argv[]) {
    if ((argc > 3) || (argc < 2)) {
        printf("You input wrong number arguments!\n");
        return -1;
    }

    if ((strcmp(argv[1],"-v")) == 0) {  //提供版本号和作者信息
        printf("scread   version:0.1\n");
        printf("Author   shining\n");
        printf("Mail:shiningning1984@gmail.com\n");
        return 0;
    }else if ((strcmp(argv[1],"-help")) == 0) {  //提供帮助说明
        printf("scread <filename>              The scread will output all the AST nodes' information\n");
        printf("scread <filename> <keyword>    The scread will output the AST nodes' matched the keyword.\n");
        printf("scread -v                      The scread will output the version information.\n");
        printf("scread -help                   The scread will output the help information.\n");
        return 0;
    }else {
        int result = open(argv[1], O_RDONLY);  //异常处理：打不开要分析的文件的情况
        if (result == -1) {
            printf("Can't open the file: %s.\n", argv[1]);
            return -1;
        }
    }

    numOfArgc = argc;
    if (numOfArgc == 3) {
        findingString = argv[2];
    }

    CXIndex Index = clang_createIndex(0,0);
    CXTranslationUnit TU = clang_parseTranslationUnit(Index, 0, argv, argc,
                                                      0, 0,
                                                      CXTranslationUnit_None);
    CXCursor C = clang_getTranslationUnitCursor(TU);

    printSpelling(C);
    printKindSpelling(C);
    printLocation(C);
    unsigned int treeLevel = 0;
    clang_visitChildren(C, printVisitor, &treeLevel);
    printf("%p\n",&treeLevel);
    unsigned int *p=&treeLevel;
  printf("%d\n",*p);

    clang_disposeTranslationUnit(TU);
    clang_disposeIndex(Index);
    return 0;
}
